﻿/*
 * UI管理类：
 *      把需要管理的UI先在Assets/AssetBundles/UIConfig.json中填好对应的名称和目录。
 *      IsAB为ture则从AssetBundles目录下加载，为false则从Resources目录下加载
 *      然后调用 UIManager.Instance.OpenUI("UIName"); 即可
 */
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ZLMsg;

namespace ZL_Framework
{
    /// <summary>
    /// UI管理器
    /// </summary>
    [StartManagerAttribute]
    public class UIManager : MonoSingleton<UIManager>, IMsgReceiver
    {
        private Transform mBackUIRoot;
        public Transform BackUIRoot
        {
            get
            {
                if (mBackUIRoot == null)
                {
                    mBackUIRoot = GameObject.Find("UIRoot/BackUI").transform;
                }
                return mBackUIRoot;
            }
        }

        private Transform mPopUIRoot;
        public Transform PopUIRoot
        {
            get
            {
                if (mPopUIRoot == null)
                {
                    mPopUIRoot = GameObject.Find("UIRoot/PopUI").transform;
                }
                return mPopUIRoot;
            }
        }

        private Transform mTopUIRoot;
        public Transform TopUIRoot
        {
            get
            {
                if (mTopUIRoot == null)
                {
                    mTopUIRoot = GameObject.Find("UIRoot/TopUI").transform;
                }
                return mTopUIRoot;
            }
        }

        public Dictionary<string, UIInfo> UIConfigDic = new Dictionary<string, UIInfo>();
        public Dictionary<string, IUIPanel> CurrentUIDic = new Dictionary<string, IUIPanel>();

        protected override void Destroy()
        {
            UIConfigDic = null;
            CurrentUIDic = null;
        }

        protected override void Init()
        {
            LoadUIConfig();
            this.RegisterLogicMsg(MsgName.MSG_RES_UPDATE_END, (param) =>
             {
                 LoadUIConfig();
             });
        }

        /// <summary>
        /// 读取UIConfig
        /// </summary>
        public void LoadUIConfig()
        {
            UIConfigDic?.Clear();
            AssetBundlesManager.Instance.LoadAsset(AppConfig.ResPath + "/Config", AppConfig.ResPath + "/Config/UIConfig.json", (obj) =>
              {
                  if (obj != null)
                  {
                      UIConfig uiConfig = (obj as TextAsset).text.EncodeToObject<UIConfig>();
                      LogTool.Instance.Log("UIConfig 加载成功");

                      foreach (var item in uiConfig.UIPanelList)
                      {
                          UIConfigDic.Add(item.UIName, item);
                      }
                  }
                  else
                  {
                      LogTool.Instance.LogError("UIConfig.json文件未找到，请在打包时把此文件的assetbundle资源随包！");
                  }
              });
        }

        /// <summary>
        /// 打开一个UI
        /// </summary>
        /// <param name="uiName"></param>
        /// <param name="param"></param>
        /// <param name="opened"></param>
        public void OpenUI(string uiName, IUIParam param = null, Action<IUIPanel> opened = null)
        {
            if (string.IsNullOrEmpty(uiName))
            {
                Debug.LogError("UIName is null");
                return;
            }

            LoadUI(uiName, false, param, opened);
        }

        /// <summary>
        /// Lua中打开一个UI
        /// </summary>
        /// <param name="uiName"></param>
        /// <param name="param"></param>
        /// <param name="opened"></param>
        public void LuaOpenUI(string uiName, IUIParam param = null, Action<IUIPanel> opened = null)
        {
            if (string.IsNullOrEmpty(uiName))
            {
                Debug.LogError("UIName is null");
                return;
            }

            LoadUI(uiName, true, param, opened);
        }

        /// <summary>
        /// 关闭一个UI
        /// </summary>
        /// <param name="uiName"></param>
        public void CloseUI(string uiName)
        {
            if (CurrentUIDic.ContainsKey(uiName))
            {
                IUIPanel panel = CurrentUIDic[uiName];
                panel.OnExit();
                Destroy(panel.PanelObj);
                CurrentUIDic.Remove(uiName);

                Resources.UnloadUnusedAssets();
                GC.Collect();
            }
            //IUIPanel panel = UIPanelStack.Pop();
            //panel.OnExit();

            //if(UIPanelStack.Count > 0)
            //{
            //    IUIPanel curPanel = UIPanelStack.Peek();
            //    curPanel.OnEnter();
            //}
        }

        /// <summary>
        /// 设置一个UI的可见性
        /// </summary>
        /// <param name="uiName"></param>
        /// <param name="_isActive"></param>
        public void SetUIPanelActive(string uiName, bool _isActive)
        {
            if (CurrentUIDic.ContainsKey(uiName))
            {
                IUIPanel panel = CurrentUIDic[uiName];
                panel.IsActive = _isActive;
            }
        }

        /// <summary>
        /// 根据名称获取一个UI
        /// </summary>
        /// <param name="uiName"></param>
        /// <returns></returns>
        public IUIPanel GetUI(string uiName)
        {
            if (CurrentUIDic.ContainsKey(uiName))
            {
                IUIPanel panel = CurrentUIDic[uiName];
                return panel;
            }
            else
            {
                return null;
            }
        }

        private void LoadUI(string uiName, bool isLua, IUIParam param, Action<IUIPanel> opened)
        {
            if (UIConfigDic.ContainsKey(uiName))
            {
                UIInfo info = UIConfigDic[uiName];
                string resPath = "";
                string abPath = "";
                if (info.IsAB)
                {
                    resPath = AppConfig.ResPath + info.ResPath;
                    var arr = resPath.Split('/');
                    for (int i = 0; i < arr.Length; i++)
                    {
                        if (i != arr.Length - 1)
                        {
                            abPath += arr[i] + "/";
                        }
                    }
                    abPath = abPath.Remove(abPath.Length - 1);
                }
                else
                {
                    resPath = "Assets/Resources" + info.ResPath;
                }
                resPath += ".prefab";
                if (!isLua)
                {
                    LoadUIPanel(info.UIType, abPath, resPath, uiName, param,
                        (str, obj) =>
                        {
                            LogTool.Instance.Log("UI Loaded, name: " + uiName);
                            //UIPanelStack.Push(obj);
                            CurrentUIDic.Add(uiName, obj);
                            opened?.Invoke(obj);
                        }, info.IsAB);
                }
                else
                {
                    LuaLoadUIPanel(info.UIType, abPath, resPath, uiName, param,
                        (str, obj) =>
                        {
                            LogTool.Instance.Log("Lua UI Loaded, name: " + uiName);
                            //UIPanelStack.Push(obj);
                            CurrentUIDic.Add(uiName, obj);
                            opened?.Invoke(obj);
                        }, info.IsAB);
                }
            }
            else
            {
                Debug.LogError("UIConfig.json 中不包含此 UI , name: " + uiName);
            }
        }

        /// <summary>
        /// 加载UI资源
        /// </summary>
        /// <param name="uiType">UI类型</param>
        /// <param name="bundleName">ab包名</param>
        /// <param name="assetName">资源名</param>
        /// <param name="_uiName">UI名称</param>
        /// <param name="loaded"></param>
        /// <param name="isAB"></param>
        public void LoadUIPanel(int uiType, string bundleName, string assetName, string _uiName, IUIParam param, Action<string, UIPanel> loaded = null, bool isAB = true)
        {
            AssetBundlesManager.Instance.LoadAsset(bundleName, assetName, (obj) =>
            {
                if (obj != null)
                {
                    Transform UIRoot = null;
                    switch (uiType)
                    {
                        case UIType.BackUI:
                            UIRoot = BackUIRoot;
                            break;
                        case UIType.PopUI:
                            UIRoot = PopUIRoot;
                            break;
                        case UIType.TopUI:
                            UIRoot = TopUIRoot;
                            break;
                        default:
                            break;
                    }
                    GameObject go = GameObject.Instantiate(obj, UIRoot) as GameObject;

                    go.transform.localScale = Vector3.one;
                    go.transform.localPosition = Vector3.zero;

                    UIPanel uiPanel = go.GetComponent<UIPanel>();
                    if (uiPanel == null)
                    {
                        uiPanel = go.AddComponent<UIPanel>();
                    }
                    uiPanel.UIName = _uiName;
                    uiPanel.UIType = uiType;
                    uiPanel.PanelObj = go;
                    uiPanel.OnOpen(param);
                    loaded?.Invoke(assetName, uiPanel);
                }
            }, isAB);
        }

        /// <summary>
        /// Lua加载UI资源
        /// </summary>
        /// <param name="uiType">UI类型</param>
        /// <param name="bundleName">ab包名</param>
        /// <param name="assetName">资源名</param>
        /// <param name="_uiLuaScript">UI对应的Lua脚本</param>
        /// <param name="loaded"></param>
        /// <param name="isAB"></param>
        public void LuaLoadUIPanel(int uiType, string bundleName, string assetName, string _uiLuaScript, IUIParam param, Action<string, LuaUIPanel> loaded = null, bool isAB = true)
        {
            AssetBundlesManager.Instance.LoadAsset(bundleName, assetName, (obj) =>
            {
                if (obj != null)
                {
                    Transform UIRoot = null;
                    switch (uiType)
                    {
                        case UIType.BackUI:
                            UIRoot = BackUIRoot;
                            break;
                        case UIType.PopUI:
                            UIRoot = PopUIRoot;
                            break;
                        case UIType.TopUI:
                            UIRoot = TopUIRoot;
                            break;
                        default:
                            break;
                    }
                    GameObject go = GameObject.Instantiate(obj, UIRoot) as GameObject;

                    go.transform.localScale = Vector3.one;
                    go.transform.localPosition = Vector3.zero;

                    LuaUIPanel uiPanel = go.GetComponent<LuaUIPanel>();
                    if (uiPanel == null)
                    {
                        uiPanel = go.AddComponent<LuaUIPanel>();
                    }
                    uiPanel.UIType = uiType;
                    uiPanel.PanelObj = go;
                    uiPanel.Init(_uiLuaScript);
                    uiPanel.luaOnOpen?.Invoke(param);
                    loaded?.Invoke(assetName, uiPanel);
                }
            }, isAB);
        }
    }

    public class UIInfo
    {
        public string UIName;
        public string ResPath;
        public int UIType;
        public bool IsAB;
    }

    public class UIConfig
    {
        public List<UIInfo> UIPanelList;
    }

    public interface IUIParam
    {
    }

    public class UIParam : IUIParam
    {
        public object value { get; set; }
    }
}